package com.cskaoyan.javase.oop3._2inner._1member._1basic;

import com.sun.org.apache.bcel.internal.util.BCELifier;

/**
 * 在具体研究成员内部类的访问特点之前,要明确两个原则:
 *      1.成员内部类和外围类是"好兄弟",互相访问都不受访问权限的限制.
 *      2.成员内部类对象依赖于外围类对象而存在.
 *          具体来说:
 *          a.在成员内部类的成员方法中,如何访问外围类成员?
 *              在成员内部类的成员方法中,也有隐含的this传参,指向当前(成员内部类)对象
 *              既然内部类对象已经存在了,那么外围类对象一定也存在
 *              成员内部类的成员方法中,隐含了两个对象,自身对象和外围类对象
 *              答: 直接访问
 *
 *          b.在外围类成员方法中,如何访问成员内部类成员?
 *              成员内部类对象依赖于外围类对象而存在.
 *              但反过来不成立
 *              在外围类成员方法中,存在自身对象
 *              但是没有成员内部类对象,需要创建成员内部类对象,然后访问它的成员
 *              问: 如何创建成员内部类对象?
 *              直接创建,因为已经存在外围类对象了.
 *
 *          c.在外围类的静态成员方法中,如何访问成员内部类成员?
 *              成员内部类对象依赖于外围类对象而存在.
 *              但反过来不成立
 *              在外围类的静态成员方法中,不存在任何对象
 *              这时想要创建成员内部类对象,访问它的成员,需要:
 *              先创建外围类对象,再在外围类对象的基础上,创建成员内部类对象
 *
 * 成员内部类的访问特点
 * 成员内部类的访问特点，主要从以下几个角度研究：
 *
 * 1.成员内部类内部访问外围类
 *      在成员内部类的成员方法中,访问外围类成员
 *      一般情况下,可以直接访问
 *      但是当成员内部类成员和外围类成员出现同名时:
 *          如果直接访问,由于就近原则,访问的是内部类自身的成员,如果还想要访问外围类成员
 *          成员内部类的成员方法中,隐含了两个对象:
 *          自身对象用this指向
 *          外围类对象用外围类类名.this指向
 *          以上可以用来区分同名的成员
 *  如果全局常量同名了,用类名去区分.
 *
 * 2.外围类访问成员内部类成员
 *      a.在成员方法中,直接创建成员内部类对象
 *      b.在静态成员方法中,先创建外围类对象,再创建成员内部类对象
 *
 * 3.外部类访问成员内部类成员(少见)
 *      之所以设计内部类,往往都是因为不希望外界访问这个类.所以成员内部类往往都是私有的.
 *      如果成员内部类没有私有化,那么在外部要想访问该成员内部类成员,需要经过经过三道权限:
 *          1.需要外围类的权限
 *          2.需要内部类的权限
 *          3.需要成员的权限
 *  在有权限的情况下,先创建外围类对象
 *  再创建成员内部类对象
 *
 *  在外部类中创建成员内部类的语法:
 *  外围类类名.成员内部类类名 对象名 = new 外围类类名().new 成员内部类类名();
 *
 * 4.成员内部类访问外部类成员
 * 可以访问,但是受访问权限限制
 *
 * @since 10:47
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        EnclosedClazz.InnerClazz ecic = ec.new InnerClazz();

        // 二合一
        EnclosedClazz.InnerClazz ecic2 = new EnclosedClazz().new InnerClazz();
    }

    public void test(){

    }
}

class EnclosedClazz {
    int a;
    private int b = 10;
    static int c = 20;
    static final String STR = "hello";

    public void testEnclosed() {
        // 直接创建成员内部类对象
        InnerClazz ic = new InnerClazz();
        System.out.println(ic.a);
        System.out.println(ic.b);
        System.out.println(this.a);
    }

    public static void testStatic() {
        // 先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        // 在外围类基础上,创建成员内部类对象
        InnerClazz ic = ec.new InnerClazz();

        // 以上步骤二合一,链式调用
        InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
    }

    class InnerClazz {
        int a;
        private int b = 100;
        // static int c = 20;
        static final String STR = "world";

        // 成员方法
        public void testInner(int a) {
            // 由于已经存在外围类对象,所以可以直接访问
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(EnclosedClazz.this.a);
            System.out.println(b);
            System.out.println(EnclosedClazz.c);
            System.out.println(EnclosedClazz.STR);
            System.out.println(InnerClazz.STR);
            testEnclosed();
            EnclosedClazz.testStatic();
        }
    }
}
